package com.bfly.common.util;

import com.alibaba.fastjson.JSONObject;
import com.bfly.core.base.entity.RemoteResponse;
import com.bfly.core.enums.SysError;
import com.bfly.core.exception.ServiceResponseException;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.StatusLine;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.UnsupportedEncodingException;
import java.util.*;


/**
 * 基于网络操作工具类
 *
 * @author 长沙商脉科技有限公司
 * 2014-4-3 下午03:46:38
 */
public class NetUtil {

    private static CloseableHttpClient httpClient;

    static {
        HttpClientBuilder builder = HttpClientBuilder.create();
        builder.addInterceptorFirst((HttpRequestInterceptor) (request, context) -> {
            request.addHeader("User-Agent", "BFlyMallServer/1.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36");
            request.addHeader("Accept-Language", "zh-CN");
        });
        httpClient = builder.build();
    }

    /**
     * 构造httpclient
     *
     * @author 长沙商脉科技有限公司
     * @date 2020/12/2 13:00
     */
    public static CloseableHttpClient getHttpClient() {
        return httpClient;
    }

    /**
     * 封装响应结果
     *
     * @author 长沙商脉科技有限公司
     * @date 2020/12/2 13:19
     */
    private static RemoteResponse getRemoteResponse(CloseableHttpResponse response) throws Exception {
        RemoteResponse remote = new RemoteResponse();
        StatusLine statusLine = response.getStatusLine();
        remote.setCode(statusLine.getStatusCode());

        HttpEntity entity = response.getEntity();
        if (entity != null) {
            remote.setContentLength(entity.getContentLength());
            Header entityContentType = entity.getContentType();
            ContentType contentType=null;
            if(entityContentType!=null) {
                remote.setContentType(entityContentType.getValue());
                contentType = ContentType.getByMimeType(remote.getContentType());
            }
            String body;
            // 图片转为base64
            if(contentType==ContentType.IMAGE_JPEG){
                body ="data:image/jpeg;base64,"+ Base64.encodeBase64String((EntityUtils.toByteArray(entity)));
            }else if(contentType==ContentType.IMAGE_PNG){
                body ="data:image/png;base64,"+ Base64.encodeBase64String((EntityUtils.toByteArray(entity)));
            }
            else if(contentType==ContentType.IMAGE_GIF){
                body ="data:image/gif;base64,"+ Base64.encodeBase64String((EntityUtils.toByteArray(entity)));
            }
            else {
                body=EntityUtils.toString(entity,"UTF-8");
            }
            remote.setBody(body);
        }
        remote.setSuccessful(statusLine.getStatusCode() >= 200 && statusLine.getStatusCode() <= 300);
        remote.setMessage(response.getStatusLine().getReasonPhrase());

        Map<String, String> heardMap = new HashMap<>();
        Header[] headers = response.getAllHeaders();
        for (Header header : headers) {
            heardMap.put(header.getName(), header.getName());
        }
        remote.setHeaders(heardMap);
        return remote;
    }

    /**
     * 处理请求
     *
     * @author 长沙商脉科技有限公司
     * @date 2020/12/2 13:34
     */
    public static RemoteResponse doRequest(HttpRequestBase request) {
        RemoteResponse remoteResponse;
        try (CloseableHttpResponse response = getHttpClient().execute(request)) {
            remoteResponse = getRemoteResponse(response);
        } catch (Exception e) {
            throw new ServiceResponseException(SysError.REMOTE_ERROR, "远程服务异常:" + e.getMessage());
        } finally {
            request.releaseConnection();
        }
        return remoteResponse;
    }

    /**
     * get请求
     *
     * @author 长沙商脉科技有限公司
     * @date 2020/12/2 12:45
     */
    public static RemoteResponse get(String url, Map<String, Object> params, Map<String, String> headers) {
        StringBuffer sb = new StringBuffer(url);
        if (params != null && params.keySet().size() > 0) {
            Iterator iterator = params.entrySet().iterator();
            sb.append("?");
            while (iterator.hasNext()) {
                Map.Entry entry = (Map.Entry<String, String>) iterator.next();
                sb.append(entry.getKey() + "=" + entry.getValue());
                if (iterator.hasNext()) {
                    sb.append("&");
                }
            }
        }
        HttpGet request = new HttpGet(sb.toString());
        if (headers != null && headers.size() > 0) {
            headers.forEach((key, value) -> request.addHeader(key, value));
        }

        RemoteResponse remoteResponse = doRequest(request);
        return remoteResponse;
    }

    public static RemoteResponse get(String url, Map<String, Object> params) {
        return get(url, params, null);
    }

    /**
     * post请求
     *
     * @author 长沙商脉科技有限公司
     * @date 2020/12/6 12:47
     */
    public static RemoteResponse post(String url, Map<String, Object> params, Map<String, String> headers) {
        HttpPost request = new HttpPost(url);
        if (params != null && params.keySet().size() > 0) {
            List<BasicNameValuePair> list = new ArrayList<>();
            for (String key : params.keySet()) {
                list.add(new BasicNameValuePair(key, params.get(key).toString()));
            }
            UrlEncodedFormEntity entity;
            try {
                entity = new UrlEncodedFormEntity(list);
            } catch (UnsupportedEncodingException e) {
                throw new ServiceResponseException(SysError.PARAM_ERROR, "参数编码异常,请检查参数!");
            }
            request.setEntity(entity);
        }
        if (headers != null && headers.size() > 0) {
            headers.forEach((key, value) -> request.addHeader(key, value));
        }
        RemoteResponse remoteResponse = doRequest(request);
        return remoteResponse;
    }

    public static RemoteResponse post(String url, Map<String, Object> params) {
        return post(url, params, null);
    }

    /**
     * Post Json
     *
     * @author 长沙商脉科技有限公司
     * @date 2020/12/2 13:44
     */
    public static RemoteResponse post(String url, JSONObject json, Map<String, String> headers) {
        HttpPost request = new HttpPost(url);
        if (headers == null) {
            headers = new HashMap<>();
        }
        headers.put("Content-Type", "application/json; charset=utf-8");
        headers.forEach((key, value) -> request.addHeader(key, value));
        StringEntity entity = new StringEntity(json.toJSONString(), "UTF-8");
        request.setEntity(entity);
        RemoteResponse remoteResponse = doRequest(request);
        return remoteResponse;
    }

    public static RemoteResponse post(String url, JSONObject json) {
        return post(url, json, null);
    }

    /**
     * post xml
     *
     * @author 长沙商脉科技有限公司
     * @date 2020/12/2 13:45
     */
    public static RemoteResponse post(String url, String xml, Map<String, String> headers) {
        HttpPost request = new HttpPost(url);
        if (headers == null) {
            headers = new HashMap<>();
        }
        headers.put("Content-Type", "application/xml; charset=utf-8");
        headers.forEach((key, value) -> request.addHeader(key, value));
        StringEntity entity = new StringEntity(xml, "UTF-8");
        request.setEntity(entity);
        RemoteResponse remoteResponse = doRequest(request);
        return remoteResponse;
    }

    public static RemoteResponse post(String url, String xml) {
        return post(url, xml, null);
    }
}
